package com.tonicgb.shared.util;

import com.alibaba.fastjson.JSONObject;

import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

public class DateUtil {
	public static String createDate()
    {
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    	String date = sdf.format(new Date());
    	return date;
    }

    public static String getNow() {
		Calendar calendar = Calendar.getInstance();
		String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(calendar.getTime());
		return now;
	}

	public static String getToday()
	{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String date = sdf.format(new Date());
		return date;
	}

	public static Date getTime()
	{
		return new Date();
	}

	public static String getYesterday(Integer day)
	{
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE,-day);
		Date time = cal.getTime();
		return new SimpleDateFormat("yyyy-MM-dd").format(time);
	}

	/*
	 * 将时间转换为时间戳
	 */
	public static String dateToStamp(String s) throws ParseException {
		String res;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date = simpleDateFormat.parse(s);
		long ts = date.getTime();
		res = String.valueOf(ts);
		return res;
	}

	/*
	 * 将时间戳转换为时间
	 */
	public static String stampToDate(String s){
		String res;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		long lt = new Long(s);
		Date date = new Date(lt);
		res = simpleDateFormat.format(date);
		return res;
	}

	/**
     * 将长时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss
     *
     * @param strDate
     * @return
     */
	public static Date strToDateLong(String strDate) {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		ParsePosition pos = new ParsePosition(0);
		Date strtodate = formatter.parse(strDate, pos);
		return strtodate;
	}

	public static String date2String(Date date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return simpleDateFormat.format(date);
	}

	public static String date2LongString(Date date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
		return simpleDateFormat.format(date);
	}

	/**
	 * 把日期字符串格式化成日期类型
	 *
	 * @param dateStr
	 * @param format
	 * @return
	 */
	public static Date convert2Date(String dateStr, String format) {
		SimpleDateFormat simple = new SimpleDateFormat(format);
		try {
			simple.setLenient(false);
			return simple.parse(dateStr);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 把日期字符串格式化成日期类型
	 *
	 * @param dateStr
	 * @return
	 */
	public static Date convert2Date(String dateStr) {
		String format = "yyyy-MM-dd HH:mm:ss";
		SimpleDateFormat simple = new SimpleDateFormat(format);
		try {
			simple.setLenient(false);
			return simple.parse(dateStr);
		} catch (Exception e) {
			return null;
		}
	}

	//时间戳转DATE（13位时间戳）
	public static Date timestampToDate(long timestamp){

		return new Date(timestamp);
	}

	/**
	 * 把日期类型格式化成字符串
	 *
	 * @param date
	 * @param format
	 * @return
	 */
	public static String convert2String(Date date, String format) {
		SimpleDateFormat formater = new SimpleDateFormat(format);
		try {
			return formater.format(date);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 把日期类型格式化成字符串
	 *
	 * @param date
	 * @return
	 */
	public static String convert2String(Date date) {
		String format = "yyyy-MM-dd HH:mm:ss";
		SimpleDateFormat formater = new SimpleDateFormat(format);
		try {
			return formater.format(date);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 获取当前日期
	 *
	 * @param format
	 * @return
	 */
	public static String getCurrentDate(String format) {
		return new SimpleDateFormat(format).format(new Date());
	}

	/**
	 * 获取时间戳
	 *
	 * @return
	 */
	public static long getTimestamp() {
		return System.currentTimeMillis();
	}

	/**
	 * 获取月份的天数
	 *
	 * @param year
	 * @param month
	 * @return
	 */
	public static int getDaysOfMonth(int year, int month) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(year, month - 1, 1);
		return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 获取日期的年
	 *
	 * @param date
	 * @return
	 */
	public static int getYear(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.YEAR);
	}

	/**
	 * 获取日期的月
	 *
	 * @param date
	 * @return
	 */
	public static int getMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.MONTH) + 1;
	}

	/**
	 * 获取日期的日
	 *
	 * @param date
	 * @return
	 */
	public static int getDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.DATE);
	}

	/**
	 * 获取日期的时
	 *
	 * @param date
	 * @return
	 */
	public static int getHour(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.HOUR);
	}

	/**
	 * 获取日期的分种
	 *
	 * @param date
	 * @return
	 */
	public static int getMinute(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.MINUTE);
	}

	/**
	 * 获取日期的秒
	 *
	 * @param date
	 * @return
	 */
	public static int getSecond(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.SECOND);
	}

	/**
	 * 获取星期几
	 *
	 * @param date
	 * @return
	 */
	public static int getWeekDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
		return dayOfWeek - 1;
	}

	/**
	 * 获取哪一年共有多少周
	 *
	 * @param year
	 * @return
	 */
	public static int getMaxWeekNumOfYear(int year) {
		Calendar c = new GregorianCalendar();
		c.set(year, Calendar.DECEMBER, 31, 23, 59, 59);
		return getWeekNumOfYear(c.getTime());
	}

	/**
	 * 取得某天是一年中的多少周
	 *
	 * @param date
	 * @return
	 */
	public static int getWeekNumOfYear(Date date) {
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.setMinimalDaysInFirstWeek(7);
		c.setTime(date);
		return c.get(Calendar.WEEK_OF_YEAR);
	}

	/**
	 * 取得某天所在周的第一天
	 *
	 * @return
	 */
	public static Date getFirstDayOfWeek(Date date) {
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
		return c.getTime();
	}

	/**
	 * 取得某天所在周的最后一天
	 *
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfWeek(Date date) {
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6);
		return c.getTime();
	}

	/**
	 * 取得某年某周的第一天 对于交叉:2008-12-29到2009-01-04属于2008年的最后一周,2009-01-05为2009年第一周的第一天
	 *
	 * @param year
	 * @param week
	 * @return
	 */
	public static Date getFirstDayOfWeek(int year, int week) {
		Calendar calFirst = Calendar.getInstance();
		calFirst.set(year, 0, 7);
		Date firstDate = getFirstDayOfWeek(calFirst.getTime());

		Calendar firstDateCal = Calendar.getInstance();
		firstDateCal.setTime(firstDate);

		Calendar c = new GregorianCalendar();
		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, Calendar.JANUARY);
		c.set(Calendar.DATE, firstDateCal.get(Calendar.DATE));

		Calendar cal = (GregorianCalendar) c.clone();
		cal.add(Calendar.DATE, (week - 1) * 7);
		firstDate = getFirstDayOfWeek(cal.getTime());

		return firstDate;
	}

	/**
	 * 取得某年某周的最后一天 对于交叉:2008-12-29到2009-01-04属于2008年的最后一周, 2009-01-04为
	 * 2008年最后一周的最后一天
	 *
	 * @param year
	 * @param week
	 * @return
	 */
	public static Date getLastDayOfWeek(int year, int week) {
		Calendar calLast = Calendar.getInstance();
		calLast.set(year, 0, 7);
		Date firstDate = getLastDayOfWeek(calLast.getTime());

		Calendar firstDateCal = Calendar.getInstance();
		firstDateCal.setTime(firstDate);

		Calendar c = new GregorianCalendar();
		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, Calendar.JANUARY);
		c.set(Calendar.DATE, firstDateCal.get(Calendar.DATE));

		Calendar cal = (GregorianCalendar) c.clone();
		cal.add(Calendar.DATE, (week - 1) * 7);
		Date lastDate = getLastDayOfWeek(cal.getTime());

		return lastDate;
	}

	private static Date add(Date date, int calendarField, int amount) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		} else {
			Calendar c = Calendar.getInstance();
			c.setTime(date);
			c.add(calendarField, amount);
			return c.getTime();
		}
	}

	/*
	 * 1则代表的是对年份操作， 2是对月份操作， 3是对星期操作， 5是对日期操作， 11是对小时操作， 12是对分钟操作， 13是对秒操作， 14是对毫秒操作
	 */

	/**
	 * 增加年
	 *
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addYears(Date date, int amount) {
		return add(date, 1, amount);
	}

	/**
	 * 增加月
	 *
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addMonths(Date date, int amount) {
		return add(date, 2, amount);
	}

	/**
	 * 增加周
	 *
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addWeeks(Date date, int amount) {
		return add(date, 3, amount);
	}

	/**
	 * 增加天
	 *
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addDays(Date date, int amount) {
		return add(date, 5, amount);
	}

	/**
	 * 增加时
	 *
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addHours(Date date, int amount) {
		return add(date, 11, amount);
	}

	/**
	 * 增加分
	 *
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addMinutes(Date date, int amount) {
		return add(date, 12, amount);
	}

	/**
	 * 增加秒
	 *
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addSeconds(Date date, int amount) {
		return add(date, 13, amount);
	}

	/**
	 * 增加毫秒
	 *
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addMilliseconds(Date date, int amount) {
		return add(date, 14, amount);
	}

	/**
	 * time差
	 *
	 * @param before
	 * @param after
	 * @return
	 */
	public static long diffTimes(Date before, Date after) {
		return after.getTime() - before.getTime();
	}

	/**
	 * 秒差
	 *
	 * @param before
	 * @param after
	 * @return
	 */
	public static long diffSecond(Date before, Date after) {
		return (after.getTime() - before.getTime()) / 1000;
	}

	/**
	 * 分种差
	 *
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffMinute(Date before, Date after) {
		return (int) (after.getTime() - before.getTime()) / 1000 / 60;
	}

	/**
	 * 时差
	 *
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffHour(Date before, Date after) {
		return (int) (after.getTime() - before.getTime()) / 1000 / 60 / 60;
	}

	/**
	 * 天数差
	 *
	 * @return
	 */
	public static int diffDay(Date before, Date after) {
		return Integer.parseInt(String.valueOf(((after.getTime() - before.getTime()) / 86400000)));
	}

	/**
	 * 月差
	 *
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffMonth(Date before, Date after) {
		int monthAll = 0;
		int yearsX = diffYear(before, after);
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(before);
		c2.setTime(after);
		int monthsX = c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
		monthAll = yearsX * 12 + monthsX;
		int daysX = c2.get(Calendar.DATE) - c1.get(Calendar.DATE);
		if (daysX > 0) {
			monthAll = monthAll + 1;
		}
		return monthAll;
	}

	/**
	 * 年差
	 *
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffYear(Date before, Date after) {
		return getYear(after) - getYear(before);
	}

	/**
	 * 设置23:59:59
	 *
	 * @param date
	 * @return
	 */
	public static Date setEndDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTime();
	}

	/**
	 * 设置00:00:00
	 *
	 * @param date
	 * @return
	 */
	public static Date setStartDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 00);
		calendar.set(Calendar.MINUTE, 00);
		calendar.set(Calendar.SECOND, 00);
		calendar.set(Calendar.MILLISECOND, 00);
		return calendar.getTime();
	}

	public static List<String> getHours() {
		List<String> list = new ArrayList<>();
		int i = 0;
		while (i < 24) {
			if (i < 10) {
				list.add("0" + i + ":00");
			} else {
				list.add(i + "" + ":00");
			}
			i++;
		}
		return list;
	}


	/**
	 * 获取系统当前月 start and end
	 */
	public static JSONObject startEndMonth(JSONObject jsonObject) {
		Calendar cale = Calendar.getInstance();
		// 获取当月第一天和最后一天
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		String firstday, lastday;
		// 获取前月的第一天
		cale = Calendar.getInstance();
		cale.add(Calendar.MONTH, 0);
		cale.set(Calendar.DAY_OF_MONTH, 1);
		firstday = format.format(cale.getTime());
		// 获取前月的最后一天
		cale = Calendar.getInstance();
		cale.add(Calendar.MONTH, 1);
		cale.set(Calendar.DAY_OF_MONTH, 0);
		lastday = format.format(cale.getTime());

		if (jsonObject == null) {
			jsonObject = new JSONObject();
		}

		jsonObject.put("startMonth", firstday);
		jsonObject.put("endMonth", lastday);
		Date date = new Date();
		jsonObject.put("count", getDaysOfMonth(date.getYear(), date.getMonth() + 1) + "");
		return jsonObject;
	}

	//java8获取某天、某周、某月、某季度和某年的起始时间

	/**
	 * 获取某天的开始日期
	 *
	 * @param offset 0今天，1明天，-1昨天，依次类推
	 * @return
	 */
	public static LocalDateTime dayStart(int offset) {
		return LocalDate.now().plusDays(offset).atStartOfDay();
	}

	/**
	 * 获取某天的开始日期
	 *
	 * @param offset 0今天，1明天，-1昨天，依次类推
	 * @return
	 */
	public static LocalDateTime dayStart(LocalDateTime dateTime, int offset) {
		return dateTime.toLocalDate().plusDays(offset).atStartOfDay();
	}

	/**
	 * 获取此刻与相对当天第day天的起始时间相隔的秒数。day为0表示今天的起始时间；1明天，2后天，-1昨天，-2前天等，依次例推。
	 *
	 * @param day
	 * @return
	 */
	public static int ttl(int day) {
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime time = LocalDate.now().plusDays(day).atStartOfDay();
		int ttl = (int) Duration.between(now, time).toMillis() / 1000;
		return ttl;
	}

	/**
	 * 获取某周的开始日期
	 *
	 * @param offset 0本周，1下周，-1上周，依次类推
	 * @return
	 */
	public static LocalDate weekStart(int offset) {
		LocalDate localDate = LocalDate.now().plusWeeks(offset);
		return localDate.with(DayOfWeek.MONDAY);
	}

	/**
	 * 获取某月的开始日期
	 *
	 * @param offset 0本月，1下个月，-1上个月，依次类推
	 * @return
	 */
	public static LocalDate monthStart(int offset) {
		return LocalDate.now().plusMonths(offset).with(TemporalAdjusters.firstDayOfMonth());
	}

	/**
	 * 获取某季度的开始日期
	 * 季度一年四季， 第一季度：2月-4月， 第二季度：5月-7月， 第三季度：8月-10月， 第四季度：11月-1月
	 *
	 * @param offset 0本季度，1下个季度，-1上个季度，依次类推
	 * @return
	 */
	public static LocalDate quarterStart(int offset) {
		final LocalDate date = LocalDate.now().plusMonths(offset * 3);
		int month = date.getMonth().getValue();//当月
		int start = 0;
		if (month >= 2 && month <= 4) {//第一季度
			start = 2;
		} else if (month >= 5 && month <= 7) {//第二季度
			start = 5;
		} else if (month >= 8 && month <= 10) {//第三季度
			start = 8;
		} else if ((month >= 11 && month <= 12)) {//第四季度
			start = 11;
		} else if (month == 1) {//第四季度
			start = 11;
			month = 13;
		}
		return date.plusMonths(start - month).with(TemporalAdjusters.firstDayOfMonth());
	}

	/**
	 * 获取某年的开始日期
	 *
	 * @param offset 0今年，1明年，-1去年，依次类推
	 * @return
	 */
	public static LocalDate yearStart(int offset) {
		return LocalDate.now().plusYears(offset).with(TemporalAdjusters.firstDayOfYear());
	}

	//获得时间戳
	public static Long getMilli(LocalDateTime time) {
		Long mill = time.toInstant(ZoneOffset.of("+8")).toEpochMilli();
		return mill;
	}

	//获得时间戳
	public static Long getMilli(LocalDate time) {
		Long mill = time.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
		return mill;
	}

	/**
	 * 获取当前时间时间戳
	 *
	 * @return
	 */
	public static Long getMilli() {
		return LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
	}

	/**
	 * LocalDateTime时间转字符串
	 *
	 * @param time
	 * @return
	 */
	public static String localDateToStr(LocalDateTime time) {
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		String localTime = df.format(time);
		return localTime;
	}

	/**
	 * LocalDateTime时间转时间戳（毫秒）
	 *
	 * @param time
	 * @return
	 */
	public static Long localDateToTimeStamp(LocalDateTime time) {
		Long mill = time.toInstant(ZoneOffset.of("+8")).toEpochMilli();
		return mill;
	}

	/**
	 * 时间戳通过LocalDateTime转时间字符串
	 *
	 * @param timestamp
	 * @return
	 */
	public static String timeStampToStr(Long timestamp) {
		Instant instant = Instant.ofEpochMilli(timestamp);
		LocalDateTime time = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		String localTime = df.format(time);
		return localTime;
	}

	/**
	 * 时间戳通过LocalDateTime转时间字符串
	 *
	 * @param timestamp
	 * @return
	 */
	public static String timeStampToStr(Long timestamp, String format) {
		Instant instant = Instant.ofEpochMilli(timestamp);
		LocalDateTime time = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
		DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
		String localTime = df.format(time);
		return localTime;
	}

	/**
	 * 时间字符串通过LocalDateTime转时间戳
	 *
	 * @param dateStr
	 * @return
	 */
	public static Long strToTimeStamp(String dateStr) {
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime time = LocalDateTime.parse(dateStr, df);
		Long mill = time.toInstant(ZoneOffset.of("+8")).toEpochMilli();
		return mill;
	}

	/**
	 * 时间字符串通过LocalDateTime转时间戳
	 *
	 * @param dateStr
	 * @return
	 */
	public static Long strToTimeStamp(String dateStr, String format) {
		DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
		LocalDateTime time = LocalDateTime.parse(dateStr, df);
		Long mill = time.toInstant(ZoneOffset.of("+8")).toEpochMilli();
		return mill;
	}

	/**
	 * 时间字符串通过LocalDateTime转时间戳
	 *
	 * @param dateStr
	 * @return
	 */
	public static Long strToTimeStamp2(String dateStr) {
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		LocalDate time = LocalDate.parse(dateStr, df);
		LocalDateTime localDateTime = time.atStartOfDay();
		Long mill = localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
		return mill;
	}

	/**
	 * 时间戳转LocalDateTime
	 *
	 * @param timeStamp
	 * @return
	 */
	public static LocalDateTime timeStampToLocalDate(long timeStamp) {
		if(timeStamp > 999999999999999L){
			timeStamp = timeStamp / 1000;
		}
		if(timeStamp > 999999999999L){
			timeStamp = timeStamp / 1000;
		}
		LocalDateTime dateTime = LocalDateTime.ofEpochSecond(timeStamp, 0, ZoneOffset.ofHours(8));
		return dateTime;
	}

	/* 获取当前日期,指定格式
	 * 描述:<描述函数实现的功能>.
	 *
	 * @return
	 */
	public static String nowDate(String DATE_FORMAT) {
		SimpleDateFormat dft = new SimpleDateFormat(DATE_FORMAT);
		return dft.format(new Date());
	}


	/**
	 * 获取当前日期,指定格式
	 * 描述:<描述函数实现的功能>.
	 *
	 * @return
	 */
	public static Integer getNowTime() {
		long t = (System.currentTimeMillis()/1000L);
		return Integer.parseInt(String.valueOf(t));
	}

}
